package service

import (
	"context"
	"dy/internal/api/store"
	"dy/internal/models"
	"dy/pkg/util"
	"errors"
)

type RelationSrv interface {
	Action(ctx context.Context, param map[string]interface{}) error
	FollowList(ctx context.Context, userId int) ([]map[string]interface{}, error)
	FollowerList(ctx context.Context, userId int) ([]map[string]interface{}, error)
	FriendList(ctx context.Context, userId int) ([]map[string]interface{}, error)
}

type relationService struct {
	store store.Factory
}

func (u *relationService) Action(ctx context.Context, param map[string]interface{}) error {
	var dyUserRelation *models.DyUserRelation
	err := util.StructTo(&param, &dyUserRelation)
	if err != nil {
		return err
	}

	if param["action_type"].(int) == 1 {
		_, flag, err := u.store.Relation().Get(ctx, dyUserRelation)
		if err != nil {
			return err
		}
		if flag == true {
			return nil
		}

		_, err = u.store.Relation().Create(ctx, dyUserRelation)
		if err != nil {
			return err
		}
	} else if param["action_type"].(int) == 2 {
		userRelation, flag, err := u.store.Relation().Get(ctx, dyUserRelation)
		if err != nil {
			return err
		}
		if flag == false {
			return nil
		}

		_, err = u.store.Relation().Del(ctx, userRelation.Id)
		if err != nil {
			return err
		}
	} else {
		return errors.New("wrong action_type")
	}

	return nil
}

func (u *relationService) FollowList(ctx context.Context, userId int) ([]map[string]interface{}, error) {
	search := map[string]interface{}{}
	search["user_id"] = userId

	list, _, err := u.store.Relation().Find(ctx, search, "add_time", "")
	if err != nil {
		return nil, err
	}
	result := make([]map[string]interface{}, 0)

	for _, element := range list {
		dyUser, flag, err := u.store.User().Get(ctx, &models.DyUser{Id: element.FollowId})
		if flag == false {
			return nil, errors.New("the author is not exist")
		}
		if err != nil {
			return nil, err
		}

		_, followCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"user_id": dyUser.Id}, "add_time", "")
		if err != nil {
			return nil, err
		}
		_, followerCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"follow_id": dyUser.Id}, "add_time", "")
		if err != nil {
			return nil, err
		}
		_, isFollow, err := u.store.Relation().Get(ctx, &models.DyUserRelation{UserId: userId, FollowId: dyUser.Id})
		if err != nil {
			return nil, err
		}

		user := map[string]interface{}{
			"id":             dyUser.Id,
			"name":           dyUser.Name,
			"follow_count":   followCount,
			"follower_count": followerCount,
			"is_follow":      isFollow,
		}

		result = append(result, user)
	}

	return result, nil
}

func (u *relationService) FollowerList(ctx context.Context, userId int) ([]map[string]interface{}, error) {
	search := map[string]interface{}{}
	search["follow_id"] = userId

	list, _, err := u.store.Relation().Find(ctx, search, "add_time", "")
	if err != nil {
		return nil, err
	}
	result := make([]map[string]interface{}, 0)

	for _, element := range list {
		dyUser, flag, err := u.store.User().Get(ctx, &models.DyUser{Id: element.UserId})
		if flag == false {
			return nil, errors.New("the author is not exist")
		}
		if err != nil {
			return nil, err
		}

		_, followCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"user_id": dyUser.Id}, "", "")
		if err != nil {
			return nil, err
		}
		_, followerCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"follow_id": dyUser.Id}, "", "")
		if err != nil {
			return nil, err
		}
		_, isFollow, err := u.store.Relation().Get(ctx, &models.DyUserRelation{UserId: userId, FollowId: dyUser.Id})
		if err != nil {
			return nil, err
		}

		user := map[string]interface{}{
			"id":             dyUser.Id,
			"name":           dyUser.Name,
			"follow_count":   followCount,
			"follower_count": followerCount,
			"is_follow":      isFollow,
		}

		result = append(result, user)
	}

	return result, nil
}

func (u *relationService) FriendList(ctx context.Context, userId int) ([]map[string]interface{}, error) {
	search := map[string]interface{}{}
	search["user_id"] = userId

	list, _, err := u.store.Relation().Find(ctx, search, "add_time", "")
	if err != nil {
		return nil, err
	}
	result := make([]map[string]interface{}, 0)

	for _, element := range list {
		_, isFriend, err := u.store.Relation().Get(ctx, &models.DyUserRelation{UserId: element.FollowId, FollowId: element.UserId})
		if isFriend == false {
			continue
		}
		if err != nil {
			return nil, err
		}

		dyUser, flag, err := u.store.User().Get(ctx, &models.DyUser{Id: element.FollowId})
		if flag == false {
			return nil, errors.New("the author is not exist")
		}
		if err != nil {
			return nil, err
		}

		_, followCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"user_id": dyUser.Id}, "", "")
		if err != nil {
			return nil, err
		}
		_, followerCount, err := u.store.Relation().Find(ctx, map[string]interface{}{"follow_id": dyUser.Id}, "", "")
		if err != nil {
			return nil, err
		}
		_, isFollow, err := u.store.Relation().Get(ctx, &models.DyUserRelation{UserId: userId, FollowId: dyUser.Id})
		if err != nil {
			return nil, err
		}

		user := map[string]interface{}{
			"id":             dyUser.Id,
			"name":           dyUser.Name,
			"follow_count":   followCount,
			"follower_count": followerCount,
			"is_follow":      isFollow,
		}

		result = append(result, user)
	}

	return result, nil
}

func NewRelationService(s *service) RelationSrv {
	return &relationService{
		store: s.store,
	}
}
